﻿using System;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Windows;

namespace ProxyToggle
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml 
    /// // TODO: setup non-implemented error catch handling
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Registry Keys definitions

        /// <summary>
        /// The AutoConfigURLSubKey stores the path to the proxy server (.pac file)
        /// </summary>
        private readonly string _autoConfigURLSubKey = ConfigurationManager.AppSettings["AutoConfigURLSubKey"];
        /// <summary>
        /// MainStartPageSubKey is the browser start page as determined through Group Policy
        /// </summary>
        private readonly string _mainStartPageSubKey = ConfigurationManager.AppSettings["MainStartPageSubKey"]; 
        /// <summary>
        /// StartPageSubKey is the browser start page. This SubKey owns two keys used for this application: DefaultStartPage and StartPage.
        /// </summary>
        private readonly string _startPageSubKey = ConfigurationManager.AppSettings["StartPageSubKey"];

        #endregion

        #region Proxy start page definitions

        /// <summary>
        /// The start page to load when the proxy is set to On.
        /// </summary>
        private readonly string _proxyOnStartPage = ConfigurationManager.AppSettings["ProxyOnStartPage"];
        /// <summary>
        /// The start page to load when the proxy is set to Off.
        /// </summary>
        private readonly string _proxyOffStartPage = ConfigurationManager.AppSettings["ProxyOffStartPage"];

        #endregion

        #region Messages for Windows Error logs
        private const string InitializingErrorMessage = "ProxyToggle - Initializing Error";
        private const string TurningOnErrorMessage = "ProxyToggle - Turning On Error";
        private const string TurningOffErrorMessage = "ProxyToggle - Turning Off Error";
        #endregion


        /// <summary>
        /// IsChecked dependecy property
        /// </summary>
        public static readonly DependencyProperty IsCheckedProperty =
            DependencyProperty.Register("IsChecked", typeof(bool), typeof(MainWindow), new PropertyMetadata(default(bool)));

        public Boolean IsChecked
        {
            get { return (bool)GetValue(IsCheckedProperty); }
            set { SetValue(IsCheckedProperty, value); }
        }
        /// <summary>
        /// The path to %TEMP% used to store the current registry proxy path when switching off the proxy
        /// </summary>
        private readonly string _tempPath = Environment.GetEnvironmentVariable("TEMP"); 
        private readonly ModifyRegistry _modifyRegistry;



        public MainWindow()
        {

            InitializeComponent();

            try
            {
                _modifyRegistry = new ModifyRegistry();
                
                // find the current proxy path value in the Registry
                var proxyUrl = _modifyRegistry.Read(_autoConfigURLSubKey, "AutoConfigURL");

                // set the current state for the UI to be checked or unchecked
                IsChecked = !string.IsNullOrEmpty(proxyUrl);

            }
            catch (Exception ex)
            {
                EventLog.WriteEntry(InitializingErrorMessage, ex.Message);
            }

        }

      
        /// <summary>
        /// Proxy ON 
        /// 
        /// Writes the specified start pages to the pre-defined subkeys.
        /// </summary>
        private void HorizontalToggleSwitch_Checked(object sender, RoutedEventArgs e)
        {
            FileStream fs = null;
            StreamReader sr = null;

            try
            {
                // find the current proxy path value in the Registry
                var proxyUrl = _modifyRegistry.Read(_autoConfigURLSubKey, "AutoConfigURL");

                // if it doesn't exist, try to read the proxy value form the stored file (if it's created)
                if (string.IsNullOrEmpty(proxyUrl))
                {
                    string storedProxyURL = null;

                    if (File.Exists(_tempPath + "\\AutoConfigURL.txt"))
                    {
                        fs = new FileStream(_tempPath + "/AutoConfigURL.txt",
                                                FileMode.Open, FileAccess.Read);
                        sr = new StreamReader(fs);
                        storedProxyURL = sr.ReadLine();

                        sr.Close();
                        fs.Close();

                    }

                    // write the stored value to the Registry
                    _modifyRegistry.Write("AutoConfigURL", storedProxyURL, _autoConfigURLSubKey);
                }

                // set the start page to proxy On
                _modifyRegistry.Write("Start Page", _proxyOnStartPage, _startPageSubKey);
                _modifyRegistry.Write("Default_Page_URL", _proxyOnStartPage, _startPageSubKey);
                _modifyRegistry.Write("Start Page", _proxyOnStartPage, _mainStartPageSubKey);

                // close out any existing IE instances
                CloseIE();
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry(TurningOnErrorMessage, ex.Message);

                if (sr != null) sr.Close();
                if (fs != null) fs.Close();
            }
        }
        
        /// <summary>
        /// Proxy OFF 
        /// 
        /// This backups the AutoConfigURL path found in the Registy to a temp file created in %TEMP% for restoration later.  
        /// </summary>
        private void HorizontalToggleSwitch_Unchecked(object sender, RoutedEventArgs e)
        {
            FileStream fs = null;
            StreamWriter sw = null;

            try
            {
                // set the start page to proxy Off
                _modifyRegistry.Write("Start Page", _proxyOffStartPage, _startPageSubKey);
                _modifyRegistry.Write("Default_Page_URL", _proxyOffStartPage, _startPageSubKey);
                _modifyRegistry.Write("Start Page", _proxyOffStartPage, _mainStartPageSubKey);

                // get the current proxy setting before erasing and write to file
                var storedProxyURL = _modifyRegistry.Read(_autoConfigURLSubKey, "AutoConfigURL");

                if (!string.IsNullOrEmpty(storedProxyURL))
                {
                    fs = new FileStream(_tempPath + "/AutoConfigURL.txt",
                                            FileMode.Create, FileAccess.Write);
                    sw = new StreamWriter(fs);
                    sw.WriteLine(storedProxyURL);

                    sw.Flush();
                    sw.Close();
                    fs.Close();
                }
                
                // clear the AutoConfigURL value in registry
                _modifyRegistry.Write("AutoConfigURL", "", _autoConfigURLSubKey);

            }
           
            catch (Exception ex)
            {
                EventLog.WriteEntry(TurningOffErrorMessage, ex.Message);

                if (sw != null) sw.Close();
                if (fs != null) fs.Close();
            }

            // close out any existing IE instances
            CloseIE();

        }


        /// <summary>
        /// Kills any running instance of the IE browser process.
        /// </summary>
        private static void CloseIE()
        {
            foreach (var p in Process.GetProcessesByName("iexplore"))
            {
                try
                {
                    p.Kill();
                    p.WaitForExit(); // possibly with a timeout
                }
                catch (Win32Exception winException)
                {
                    // process was terminating or can't be terminated 
                    throw new NotImplementedException();
                }
                catch (InvalidOperationException invalidException)
                {
                    // process has already exited 
                    throw new NotImplementedException();
                }
            }
        }
    }
}
